#pragma once

#include "VConfigs.hpp"
#include "zen_audio_player.h"

class MenuGesture : public Zen::Vap::TouchHandle {
	struct ButtonInfo {
		
		Rect4f area;
//		std::function<void()>
	};
public:
	MenuGesture()
	{
	}
protected:
//	std::
};

class Gesture : public Zen::Vap::TouchHandle
{
public:
	float m_move_ep = 20.f;
	float m_peace_interval = 0.1f;
	float m_move_act_step = 60.f;
	Gesture()
	{
	}

	AppTouch & fixTouch(AppTouch & touch) {
		touch.x *= VConfigs::Get()->getViewSize().w;
		touch.y *= VConfigs::Get()->getViewSize().h;
		return touch;
	}
	virtual bool onTouchDown(AppTouch touch) {this->onTouchDown_(fixTouch(touch)); return true; }

	virtual bool onTouchMove(AppTouch touch) { this->onTouchMove_(fixTouch(touch)); return true; }

	virtual bool onTouchUp(AppTouch touch) { this->onTouchUp_(fixTouch(touch)); return true; }

	virtual bool onTouchCancel(AppTouch touch) { this->onTouchCancel_(fixTouch(touch)); return true; }

	void onTouchDown_(AppTouch const & touch)
	{
		if(m_is_touched) return;
		m_moved = { 0, 0 };
		m_moved_to_x = 0;
		m_is_moved_x = false;
		m_is_moved_y = false;
		m_start_touch = touch;
		m_last_touch = touch;
		m_last_moved_touch = touch;
		m_last_moved_time = m_touched_time = m_last_act_time = m_last_touch_time = 0;
		onStartTouch();

		LogD("      start %f", touch.y);
	}
	void onTouchMove_(AppTouch const & touch) {
		if(!m_is_touched)
		{
			LogW("Touch@Move not touched");
			return;
		}
		if(m_start_touch.no != touch.no) return;
		m_last_touch = touch;

//		auto now = Activity::Get()->getRunningTime();

		m_moved = { touch.x - m_start_touch.x, touch.y - m_start_touch.y };

		if(m_is_moved_x) {
//			this->onMoveX(m_moved.x);
			return;
		}
		if(m_is_moved_y) {
//			this->onMoveY(m_moved.y);
			return;
		}
		if(!IsFuzzyZero(m_moved.x, m_move_ep)) {
			m_is_moved_x = true;
//			this->onMoveX(m_moved.x);
			return;
		}

		if(!IsFuzzyZero(m_moved.y, m_move_ep*2)) {
			m_is_moved_y = true;
//			this->onMoveY(m_moved.y);
			return;
		}
	}
	void onTouchUp_(AppTouch const & touch) {
		if(!m_is_touched) return;
		if(m_start_touch.no != touch.no) return;

		m_is_touched = false;

		if(!m_is_moved_x) {
			if(!m_is_moved_y && IsFuzzyEqual(touch.x, m_start_touch.x, 4.f) && IsFuzzyEqual(touch.y, m_start_touch.y, 4.f)) {
				this->onTap();
			}
			else {
				float dt = m_touched_time - m_last_moved_time;
				float diff_y0 = touch.y - m_start_touch.y;
				float diff_y = touch.y - m_last_moved_touch.y;
				if(diff_y0 < -m_move_act_step) {
					if(dt < m_peace_interval)
					{
						if(diff_y < -m_move_ep) {
							this->onQuickDown();
							LogD("QuickDown~~1");
						}
					}
					else if(dt < m_peace_interval*3 && (std::abs(diff_y) / dt * m_peace_interval) > m_move_ep)
					{
						this->onQuickDown();
						LogD("QuickDown~~2");
					}
				}
//
//				if(diff_y > m_move_ep && diff_y0 > m_move_ep) {
//					this->onUp();
//				}
				LogD("Touch@ %f %f %f", dt, diff_y, diff_y0);
			}
		}
		LogD("       end %f", touch.y);

		onEndTouch();
	}
	void onTouchCancel_(AppTouch const & touch) {
		if(!m_is_touched) return;
		if(m_start_touch.no != touch.no) return;

		onEndTouch();
	}

	void onQuickDown()
	{
		if(onEvent) onEvent(GestureType::QuickDown);
//		AudioPlayer::Get()->play(GetPath("sound rotate"), 0);
		LogD("qd---");
	}
	void onUp()
	{
		LogD("qup--");
//		if(onEvent) onEvent(GestureType::);
	}
	void onTap() {
		LogD("tap");
//		AudioPlayer::Get()->play(GetPath("sound tick", 0), 0);

		for(auto & i : Object::s_all) {
			std::cout << i->getObjectName() << " " << i->getObjectID() << std::endl;
		}

		if(onEvent) onEvent(GestureType::Tap);
	}
	void onStartTouch() {
		m_is_touched = true;

		LogD("start");
		if(onEvent) onEvent(GestureType::Begin);
	}
	void onEndTouch() {
		m_is_touched = false;

		LogD("end");
		if(onEvent) onEvent(GestureType::End);
	}

	void onUpdate(float interval) {
		if(!m_is_touched) {
			return ;
		}
		m_touched_time += interval;
		if(m_is_moved_x) {
			if(m_last_act_time + 1.f/60.f < m_touched_time) {
				auto diff = m_moved.x - m_moved_to_x;
				if(diff < -m_move_act_step) {
					onEvent(GestureType::Left);
					m_last_act_time = m_touched_time;
					m_moved_to_x -= m_move_act_step;
				}
				if(diff > m_move_act_step) {
					m_last_act_time = m_touched_time;
					onEvent(GestureType::Right);
					m_moved_to_x += m_move_act_step;
				}
			}
		}
		else if(m_is_moved_y) {
			if(m_moved.y < -m_move_act_step && (m_last_act_time + 0.1f < m_touched_time)) {
				m_last_act_time = m_touched_time;
				onEvent(GestureType::Down);
			}
		}

		if(!m_is_moved_x)
		{
			float dt = m_touched_time - m_last_moved_time;
			if(dt > 0.1f) {
				if(IsFuzzyEqual(m_last_touch.y, m_last_moved_touch.y, m_move_ep)) {
					m_last_moved_time = m_last_touch_time;
					m_last_moved_touch = m_last_touch;
					LogV("Touch@update %f", dt);
				}
			}
		}
	}
	std::function<void(GestureType type)> onEvent;
protected:
	bool m_is_touched = false;
	bool m_is_moved_x = false;
	bool m_is_moved_y = false;
	AppTouch m_start_touch;
	AppTouch m_last_touch;
	AppTouch m_last_moved_touch;
	Point2 m_moved;
	float m_moved_to_x = 0;
	double m_touched_time;
	double m_last_act_time;
	double m_last_moved_time;
	double m_last_touch_time;
};
